package ru.vpitervip.server.domain;

import java.util.List;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.FetchType;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.Query;
import javax.persistence.Table;
import javax.persistence.TypedQuery;

import org.springframework.roo.addon.entity.RooEntity;
import org.springframework.roo.addon.javabean.RooJavaBean;
import org.springframework.roo.addon.tostring.RooToString;


@RooJavaBean
@RooToString
@RooEntity
@Table(name="flat")
public class Flat {
	
	private Integer location;
	
	private Integer level;
	
	private Integer roomNum;
	
	private Integer area;
	
	private String sleepPlaceNum;
	
	private String address;
	
	private String flatNumber;
	
	@ManyToOne
	private MetroStation metroStation;
	
	private Integer floor;
	
	private Integer price;
	
	private String description;
	
	@ManyToMany(fetch=FetchType.EAGER)
	@Column(unique=true)
	private List<Facility> facilities;
	
	@ManyToMany(cascade=CascadeType.ALL)
	@Column(unique=true)
	private List<Foto> fotos;
	
	private Integer deposit;
	//@Column(nullable = false, columnDefinition = "bool default false")
	private boolean hidden;
	
	private Integer displayMode;
	
	private Double lat;
	
	private Double lon;
	
	private Double significance;
	
	
	
	  public static Flat findVipFlat(Long id) {
//	    	System.out.println("findFlat:"+id);
//	    	return null;
	        if (id == null) return null;
	        TypedQuery<Flat> query=createVipFlatsQuery(Flat.class, "SELECT o"," AND o.id="+id+" ", null, null, null);
	        List<Flat> result=query.getResultList();
	        return result==null||result.size()!=1?null:result.get(0);
	    }
	
	public static long countVipFlats(List<String> facilityIds,MetroStation metroStation,Integer rooms) {
		System.out.println("countVipFlats");

       TypedQuery<Long> query=createVipFlatsQuery(Long.class, "SELECT COUNT(o)","", facilityIds, metroStation, rooms);

        long result=(Long) query.getSingleResult();
//        System.out.println("countVipFlats:"+result);
        return result;
	
	}
	
	@SuppressWarnings("unchecked")
	public static List<Flat> findVipFlats(int firstResult, int maxResults,List<String> facilityIds,MetroStation metroStation,Integer rooms) {
		System.out.println("findVipFlats");
		TypedQuery<Flat> query=createVipFlatsQuery(Flat.class, "SELECT o","", facilityIds, metroStation, rooms);
        List<Flat> result=query.setFirstResult(firstResult).setMaxResults(maxResults).getResultList();
        if (result!=null&&result.size()>0) System.out.println("findVipFlats facilities:"+result.get(0).getFacilities());
        
        return result;
        
	}
	
	
	
	
	
	


	private static <T> TypedQuery<T> createVipFlatsQuery(Class<T> type,String beginning,String ending,List<String> facilityIds,MetroStation metroStation,Integer rooms){

		String metroQuery="";
		String roomsQuery="";
		String facilitiesQuery="";
		if (metroStation!=null) metroQuery="AND o.metroStation=:metroStation";
		if (rooms!=null) roomsQuery=" AND o.roomNum"+(rooms==5?">=":"=")+":rooms ";
		if (facilityIds!=null&&facilityIds.size()>0){
			for (String facilityId:facilityIds)	facilitiesQuery+=" AND :"+facilityId+" MEMBER OF o.facilities";
		}
		TypedQuery<T> query=entityManager().createQuery(beginning+" FROM Flat o  WHERE o.displayMode>=4 AND o.hidden=false "+roomsQuery+metroQuery+facilitiesQuery+ending+"  ORDER BY o.significance DESC ", type);
		if (metroStation!=null) query.setParameter("metroStation",metroStation);
        if (rooms!=null) query.setParameter("rooms",rooms);
        if (facilityIds!=null&&facilityIds.size()>0){
			for (String facilityId:facilityIds)	{
				Facility facility=Facility.findFacility(facilityId);
				query.setParameter(facilityId,facility);;
			}
			
		}
       
        return query;
		
	}

	public Integer getDisplayMode() {
		return displayMode;
	}

	public void setDisplayMode(Integer displayMode) {
		this.displayMode = displayMode;
	}

	public Double getLat() {
		return lat;
	}

	public void setLat(Double lat) {
		this.lat = lat;
	}

	public Double getLon() {
		return lon;
	}

	public void setLon(Double lon) {
		this.lon = lon;
	}

	public Double getSignificance() {
		return significance;
	}

	public void setSignificance(Double significance) {
		this.significance = significance;
	}
	
	
	
}
